home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / perl / examples / gimpmagick < prev    next >
Encoding:
Text File  |  2000-05-21  |  21.3 KB  |  629 lines

  1. #!/usr/bin/perl
  2.  
  3. use Gimp::Feature qw(gtk perl-5.005);
  4. use Gimp 1.06 (':auto','__','N_');
  5. use Gimp::Fu;
  6. use Gtk;
  7. BEGIN { eval "use Image::Magick 1.45"; $@ and Gimp::Feature::missing ("Image::Magick version 1.45 or higher") };
  8.  
  9. $VERSION = '0.2.1';
  10.  
  11. $preview_size = 160; # max. size for image preview
  12.  
  13. # this funny little function parses the Magick.xs file
  14. sub reparse {
  15.    my $res;
  16.    $res.="%MagickTypes = (\n";
  17.    $xs = do { local(*XS,$/); open XS,"<$_[0]" or die; <XS> };
  18.    while($xs =~ /(\w+Types)\[\]\s=\s+\{([^}]+)\}/g) {
  19.       my $name=$1;
  20.       my @vals=$2=~/"([^"]+)"/g;
  21.       shift @vals if $vals[0] eq "Undefined";
  22.       $res.="   $name => sub {\n      my \$m = new Gtk::Menu;\n".
  23.             join("",map "      \$m->append(new Gtk::MenuItem '$_');\n",@vals).
  24.             "      my \$o = new Gtk::OptionMenu;\n".
  25.             "      \$o->set_menu(\$m);\n".
  26.             "      optionmenu_settext(\$o,\@_);\n".
  27.             "      \$o;\n".
  28.             "   },\n";
  29.    }
  30.    $res.=");\n\n";
  31.  
  32.    $res.="%MagickMethods = (\n";
  33.    $xs =~ /Methods\[\]\s=\s+\{\n(.+?)\s*\};/s or die;
  34.    $methods=$1;
  35.    while($methods =~ /(?:^|\n)(\s+)\{ "([^"]+)",(?: \{ (.*?))?\s*\},(?=\n\1\{|$)/gs) {
  36.       my $method=$2;
  37.       my @args=$3=~/\{"([^"]+)", (\w+)},?/gs;
  38.       $res.="   $method => [".join(",",map "'$_'",@args)."],\n";
  39.    }
  40.    $res.=");\n";
  41.  
  42.    require IO::AtomicFile;
  43.  
  44.    {
  45.       local $/;
  46.       open X,"<$0" or die;
  47.       $data=<X>;
  48.       $data=~s/(?<=\n#MAGICK#\n).*/sub magick {\n$res\n}\n/s;
  49.       my $file=IO::AtomicFile->open($0,"w");
  50.       $file->print($data);
  51.       $file->close;
  52.    }
  53. }
  54.  
  55. sub optionmenu_settext {
  56.    my ($o,$ref) = @_;
  57.    $o->signal_connect (clicked => sub {
  58.       $arg{$ref} = $_[0]->get_menu->get_active->get;
  59.    });
  60. }
  61.  
  62. sub new_entry {
  63.    my ($re,$ref)=@_;
  64.    my $e = new Gtk::Entry;
  65.    $e->signal_connect(changed => sub {
  66.       $arg{$ref}=$e->get_text;
  67.    });
  68.    $e;
  69. }
  70.  
  71. if ($ARGV[0] eq "--reparse") {
  72.    reparse("/root/cvt/ImageMagick-4.2.0/PerlMagick/Magick.xs");
  73.    exit;
  74. }
  75.  
  76. &magick;
  77.  
  78. %MagickTypes = (%MagickTypes,
  79.    'StringReference' => sub { new_entry "",@_ },
  80.    'DoubleReference' => sub { new_entry '^[0-9.E+-]+$',@_ },
  81.    'IntegerReference' => sub { new_entry '^[0-9+-]+$',@_ },
  82.    'ImageReference' => sub { new Gtk::Label "not yet supported" },
  83. );
  84.  
  85. %MagickMethods = (%MagickMethods,
  86. );
  87.  
  88. sub check {
  89.    for(values(%MagickMethods)) {
  90.       my @a=@$_;
  91.       while(@a) {
  92.          shift @a;
  93.          my $x = shift @a;
  94.          print($x," <- does not exist\n") unless $MagickTypes{$x};
  95.       }
  96.    }
  97. }
  98. #check;
  99.  
  100. # read the image pixels into an imagemagick-image
  101. sub read_pixels {
  102.    my($drawable,$im)=@_;
  103.    my $th = Gimp->tile_height;
  104.  
  105.    Gimp->tile_cache_ntiles (1 + $drawable->width / Gimp->tile_width);
  106.  
  107.    my $type = $drawable->type;
  108.    my $format;
  109.    $format = "RGB"  if $type == RGB_IMAGE;
  110.    $format = "RGBA" if $type == RGBA_IMAGE;
  111.    $format = "GRAY" if $type == GRAY_IMAGE;
  112.    die "Indexed format and GRAYA not yet supported in GimpMagick!\n" unless $format;
  113.  
  114.    my $temp = Gimp->temp_name('raw');
  115.    open TEMP,">$temp\0" or die "unable to open temporary file '$temp' for writing\n";
  116.    my ($empty,$x1,$y1,$x2,$y2) = $drawable->mask_bounds;
  117.    $x2-=$x1; $y2-=$y1;
  118.    my $region = $drawable->pixel_rgn ($x1, $y1, $x2, $y2, 0, 0);
  119.  
  120.    Gimp->progress_init ("transferring image data");
  121.    for(my $y=0; $y<$y2; $y+=$th) {
  122.       # calling internal function, sorry folks!
  123.       Gimp->progress_update ($y/$y2*100);
  124.       print TEMP $region->get_rect2(0,$y,$x2,$y2-$y > $th ? $th : $y2-$y);
  125.    }
  126.    close TEMP;
  127.    $im->Set(size => $x2.'x'.$y2);
  128.    $im->Read("$format:$temp");
  129.    unlink $temp;
  130.  
  131.    $format;
  132. }
  133.  
  134. # read the image pixels back
  135. sub write_pixels {
  136.    my($drawable,$im,$format)=@_;
  137.    my $th = Gimp->tile_height;
  138.    my $buf;
  139.  
  140.    my $temp = Gimp->temp_name('raw');
  141.  
  142.    $im->Write("$format:$temp");
  143.  
  144.    open TEMP,"<$temp\0" or die "unable to open temporary file '$temp' for writing\n";
  145.    unlink $temp;
  146.    my ($empty,$x1,$y1,$x2,$y2) = $drawable->mask_bounds;
  147.    $x2-=$x1; $y2-=$y1;
  148.  
  149.    if ($x2 ne $im->get('width') or $y2 ne $im->get('height')) {
  150.       $drawable->resize ($im->get('width','height'),0,0);
  151.       $drawable->image->selection_none;
  152.       ($x1,$y1,$x2,$y2)=(0,0,$im->get('width','height'));
  153.    }
  154.  
  155.    my $region = $drawable->get->pixel_rgn ($x1, $y1, $x2, $y2, 1, 1);
  156.  
  157.    Gimp->progress_init ("transferring image data");
  158.    my $stride = $x2*$region->bpp;
  159.    for(my $y=0; $y<$y2; $y+=$th) {
  160.       # calling internal function, sorry folks!
  161.       Gimp->progress_update ($y/$y2*100);
  162.       read TEMP,$buf,$stride*$th;
  163.       $region->set_rect2($buf,0,$y);
  164.    }
  165.    close TEMP;
  166.  
  167.    undef $region;
  168.    $drawable->merge_shadow (1);
  169.    $drawable->update ($x1, $y1, $x2, $y2);
  170.    Gimp->displays_flush;
  171. }
  172.  
  173. sub update_preview {
  174.    my ($im,$pre)=@_;
  175.    $im=$im->clone;
  176.  
  177.    while($im->get('width') > $preview_size or $im->get('height') > $preview_size) {
  178.       $im->Minify;
  179.    }
  180.    if(0==open BLOB,"-|") {
  181.       $im->Write('RGB:-');
  182.       Gimp::_exit;
  183.    }
  184.  
  185.    my($w,$h)=$im->get('width','height');
  186.    $pre->size($w,$h);
  187.    for (0..$h-1) {
  188.       read BLOB,$im,$w*3;
  189.       $pre->draw_row($im,0,$_,$w);
  190.    }
  191.    close BLOB;
  192.    $pre->draw(undef);
  193. }
  194.  
  195. # Interactively apply Image::Magick
  196. sub gimp_magick {
  197.    my ($drawable)=@_;
  198.  
  199.    Gimp::gtk_init;
  200.  
  201.    # generate main window
  202.    my $im = new Image::Magick;
  203.  
  204.    my $format = read_pixels ($drawable, $im);
  205.  
  206.    my $w = new Gtk::Dialog;
  207.  
  208.    $w->set_title ("GimpMagick! $VERSION");
  209.  
  210.    my $b = new Gtk::Button "Apply";
  211.    $b->signal_connect (clicked => sub { write_pixels ($drawable, $im, $format); main_quit Gtk });
  212.    $w->action_area->add ($b);
  213.    $b = new Gtk::Button "Cancel";
  214.    $b->signal_connect (clicked => sub { main_quit Gtk });
  215.    $w->action_area->add ($b);
  216.  
  217.    $preview = new Gtk::Preview "color";
  218.    $w->vbox->add ($preview);
  219.  
  220.    my $frame = new Gtk::Frame "Arguments";
  221.    my $cbox = new Gtk::VBox 0,0;
  222.    $frame->add($cbox);
  223.  
  224.    my $command = new Gtk::Combo;
  225.    my %args;
  226.  
  227.    $command->set_popdown_strings (sort keys %MagickMethods);
  228.    $command->set_case_sensitive (0);
  229.  
  230.    my $changed_command = sub {
  231.       $method = $command->entry->get_text;
  232.       return unless $MagickMethods{$method};
  233.       $frame->remove ($cbox);
  234.       $cbox = new Gtk::VBox 0,5;
  235.       my @args = @{$MagickMethods{$method}};
  236.       while(@args) {
  237.          %arg=();
  238.          my($name,$type)=(shift @args,shift @args);
  239.          my($hbox)=new Gtk::HBox 0,5;
  240.          $hbox->add(new Gtk::Label "$name: ");
  241.          my $widget = $MagickTypes{$type}->($name);
  242.          $hbox->add($widget);
  243.          $cbox->add($hbox);
  244.       }
  245.       $cbox->show_all;
  246.       $frame->add($cbox);
  247.    };
  248.  
  249.    $command->entry->signal_connect(changed => $changed_command);
  250.  
  251.    my $execute = new Gtk::Button "Execute!";
  252.  
  253.    $execute->signal_connect(clicked => sub {
  254.       $im->$method(%arg);
  255.       update_preview ($im, $preview);
  256.    });
  257.  
  258.    $w->vbox->add($command);
  259.    $w->vbox->add($frame);
  260.    $w->vbox->add($execute);
  261.  
  262.    update_preview ($im, $preview);
  263.  
  264.    $w->show_all;
  265.    &$changed_command;
  266.    main Gtk;
  267.    ();
  268. }
  269.  
  270. register "gimp_magick",
  271.          "access to the Image::Magick-package",
  272.          "Gimp::Magick gives you access to all methods in the Image::Magick-package. These methods often offer ".
  273.             "higher quality than equivalent Gimp methods, as well as offering more methods than Gimp itself",
  274.          "Marc Lehmann",
  275.          "Marc Lehmann",
  276.          $VERSION,
  277.          N_"<Image>/Filters/Misc/Magick...",
  278.          "*",
  279.          [
  280.          ],
  281.          sub {
  282.    my($image,$drawable)=@_;
  283.  
  284.    gimp_magick ($drawable);
  285.  
  286.    $image;
  287. };
  288.  
  289. exit main;
  290.  
  291. #MAGICK#
  292. sub magick {
  293. %MagickTypes = (
  294.    BooleanTypes => sub {
  295.       my $m = new Gtk::Menu;
  296.       $m->append(new Gtk::MenuItem 'False');
  297.       $m->append(new Gtk::MenuItem 'True');
  298.       my $o = new Gtk::OptionMenu;
  299.       $o->set_menu($m);
  300.       optionmenu_settext($o,@_);
  301.       $o;
  302.    },
  303.    ClassTypes => sub {
  304.       my $m = new Gtk::Menu;
  305.       $m->append(new Gtk::MenuItem 'DirectClass');
  306.       $m->append(new Gtk::MenuItem 'PseudoClass');
  307.       my $o = new Gtk::OptionMenu;
  308.       $o->set_menu($m);
  309.       optionmenu_settext($o,@_);
  310.       $o;
  311.    },
  312.    ColorspaceTypes => sub {
  313.       my $m = new Gtk::Menu;
  314.       $m->append(new Gtk::MenuItem 'RGB');
  315.       $m->append(new Gtk::MenuItem 'Gray');
  316.       $m->append(new Gtk::MenuItem 'Transparent');
  317.       $m->append(new Gtk::MenuItem 'OHTA');
  318.       $m->append(new Gtk::MenuItem 'XYZ');
  319.       $m->append(new Gtk::MenuItem 'YCbCr');
  320.       $m->append(new Gtk::MenuItem 'YCC');
  321.       $m->append(new Gtk::MenuItem 'YIQ');
  322.       $m->append(new Gtk::MenuItem 'YPbPr');
  323.       $m->append(new Gtk::MenuItem 'YUV');
  324.       $m->append(new Gtk::MenuItem 'CMYK');
  325.       $m->append(new Gtk::MenuItem 'sRGB');
  326.       my $o = new Gtk::OptionMenu;
  327.       $o->set_menu($m);
  328.       optionmenu_settext($o,@_);
  329.       $o;
  330.    },
  331.    CompositeTypes => sub {
  332.       my $m = new Gtk::Menu;
  333.       $m->append(new Gtk::MenuItem 'Over');
  334.       $m->append(new Gtk::MenuItem 'In');
  335.       $m->append(new Gtk::MenuItem 'Out');
  336.       $m->append(new Gtk::MenuItem 'Atop');
  337.       $m->append(new Gtk::MenuItem 'Xor');
  338.       $m->append(new Gtk::MenuItem 'Plus');
  339.       $m->append(new Gtk::MenuItem 'Minus');
  340.       $m->append(new Gtk::MenuItem 'Add');
  341.       $m->append(new Gtk::MenuItem 'Subtract');
  342.       $m->append(new Gtk::MenuItem 'Difference');
  343.       $m->append(new Gtk::MenuItem 'Bumpmap');
  344.       $m->append(new Gtk::MenuItem 'Replace');
  345.       $m->append(new Gtk::MenuItem 'ReplaceRed');
  346.       $m->append(new Gtk::MenuItem 'ReplaceGreen');
  347.       $m->append(new Gtk::MenuItem 'ReplaceBlue');
  348.       $m->append(new Gtk::MenuItem 'ReplaceMatte');
  349.       $m->append(new Gtk::MenuItem 'Blend');
  350.       $m->append(new Gtk::MenuItem 'Displace');
  351.       my $o = new Gtk::OptionMenu;
  352.       $o->set_menu($m);
  353.       optionmenu_settext($o,@_);
  354.       $o;
  355.    },
  356.    CompressionTypes => sub {
  357.       my $m = new Gtk::Menu;
  358.       $m->append(new Gtk::MenuItem 'None');
  359.       $m->append(new Gtk::MenuItem 'BZip');
  360.       $m->append(new Gtk::MenuItem 'Fax');
  361.       $m->append(new Gtk::MenuItem 'Group4');
  362.       $m->append(new Gtk::MenuItem 'JPEG');
  363.       $m->append(new Gtk::MenuItem 'LZW');
  364.       $m->append(new Gtk::MenuItem 'Runlength');
  365.       $m->append(new Gtk::MenuItem 'Zip');
  366.       my $o = new Gtk::OptionMenu;
  367.       $o->set_menu($m);
  368.       optionmenu_settext($o,@_);
  369.       $o;
  370.    },
  371.    FilterTypes => sub {
  372.       my $m = new Gtk::Menu;
  373.       $m->append(new Gtk::MenuItem 'Point');
  374.       $m->append(new Gtk::MenuItem 'Box');
  375.       $m->append(new Gtk::MenuItem 'Triangle');
  376.       $m->append(new Gtk::MenuItem 'Hermite');
  377.       $m->append(new Gtk::MenuItem 'Hanning');
  378.       $m->append(new Gtk::MenuItem 'Hamming');
  379.       $m->append(new Gtk::MenuItem 'Blackman');
  380.       $m->append(new Gtk::MenuItem 'Gaussian');
  381.       $m->append(new Gtk::MenuItem 'Quadratic');
  382.       $m->append(new Gtk::MenuItem 'Cubic');
  383.       $m->append(new Gtk::MenuItem 'Catrom');
  384.       $m->append(new Gtk::MenuItem 'Mitchell');
  385.       $m->append(new Gtk::MenuItem 'Lanczos');
  386.       $m->append(new Gtk::MenuItem 'Bessel');
  387.       $m->append(new Gtk::MenuItem 'Sinc');
  388.       my $o = new Gtk::OptionMenu;
  389.       $o->set_menu($m);
  390.       optionmenu_settext($o,@_);
  391.       $o;
  392.    },
  393.    GravityTypes => sub {
  394.       my $m = new Gtk::Menu;
  395.       $m->append(new Gtk::MenuItem 'Forget');
  396.       $m->append(new Gtk::MenuItem 'NorthWest');
  397.       $m->append(new Gtk::MenuItem 'North');
  398.       $m->append(new Gtk::MenuItem 'NorthEast');
  399.       $m->append(new Gtk::MenuItem 'West');
  400.       $m->append(new Gtk::MenuItem 'Center');
  401.       $m->append(new Gtk::MenuItem 'East');
  402.       $m->append(new Gtk::MenuItem 'SouthWest');
  403.       $m->append(new Gtk::MenuItem 'South');
  404.       $m->append(new Gtk::MenuItem 'SouthEast');
  405.       $m->append(new Gtk::MenuItem 'Static');
  406.       my $o = new Gtk::OptionMenu;
  407.       $o->set_menu($m);
  408.       optionmenu_settext($o,@_);
  409.       $o;
  410.    },
  411.    ImageTypes => sub {
  412.       my $m = new Gtk::Menu;
  413.       $m->append(new Gtk::MenuItem 'Bilevel');
  414.       $m->append(new Gtk::MenuItem 'Grayscale');
  415.       $m->append(new Gtk::MenuItem 'Palette');
  416.       $m->append(new Gtk::MenuItem 'TrueColor');
  417.       $m->append(new Gtk::MenuItem 'Matte');
  418.       $m->append(new Gtk::MenuItem 'ColorSeparation');
  419.       my $o = new Gtk::OptionMenu;
  420.       $o->set_menu($m);
  421.       optionmenu_settext($o,@_);
  422.       $o;
  423.    },
  424.    IntentTypes => sub {
  425.       my $m = new Gtk::Menu;
  426.       $m->append(new Gtk::MenuItem 'Saturation');
  427.       $m->append(new Gtk::MenuItem 'Perceptual');
  428.       $m->append(new Gtk::MenuItem 'Absolute');
  429.       $m->append(new Gtk::MenuItem 'Relative');
  430.       my $o = new Gtk::OptionMenu;
  431.       $o->set_menu($m);
  432.       optionmenu_settext($o,@_);
  433.       $o;
  434.    },
  435.    InterlaceTypes => sub {
  436.       my $m = new Gtk::Menu;
  437.       $m->append(new Gtk::MenuItem 'None');
  438.       $m->append(new Gtk::MenuItem 'Line');
  439.       $m->append(new Gtk::MenuItem 'Plane');
  440.       $m->append(new Gtk::MenuItem 'Partition');
  441.       my $o = new Gtk::OptionMenu;
  442.       $o->set_menu($m);
  443.       optionmenu_settext($o,@_);
  444.       $o;
  445.    },
  446.    LayerTypes => sub {
  447.       my $m = new Gtk::Menu;
  448.       $m->append(new Gtk::MenuItem 'Red');
  449.       $m->append(new Gtk::MenuItem 'Green');
  450.       $m->append(new Gtk::MenuItem 'Blue');
  451.       $m->append(new Gtk::MenuItem 'Matte');
  452.       my $o = new Gtk::OptionMenu;
  453.       $o->set_menu($m);
  454.       optionmenu_settext($o,@_);
  455.       $o;
  456.    },
  457.    MethodTypes => sub {
  458.       my $m = new Gtk::Menu;
  459.       $m->append(new Gtk::MenuItem 'Point');
  460.       $m->append(new Gtk::MenuItem 'Replace');
  461.       $m->append(new Gtk::MenuItem 'Floodfill');
  462.       $m->append(new Gtk::MenuItem 'FillToBorder');
  463.       $m->append(new Gtk::MenuItem 'Reset');
  464.       my $o = new Gtk::OptionMenu;
  465.       $o->set_menu($m);
  466.       optionmenu_settext($o,@_);
  467.       $o;
  468.    },
  469.    ModeTypes => sub {
  470.       my $m = new Gtk::Menu;
  471.       $m->append(new Gtk::MenuItem 'Frame');
  472.       $m->append(new Gtk::MenuItem 'Unframe');
  473.       $m->append(new Gtk::MenuItem 'Concatenate');
  474.       my $o = new Gtk::OptionMenu;
  475.       $o->set_menu($m);
  476.       optionmenu_settext($o,@_);
  477.       $o;
  478.    },
  479.    NoiseTypes => sub {
  480.       my $m = new Gtk::Menu;
  481.       $m->append(new Gtk::MenuItem 'Uniform');
  482.       $m->append(new Gtk::MenuItem 'Gaussian');
  483.       $m->append(new Gtk::MenuItem 'Multiplicative');
  484.       $m->append(new Gtk::MenuItem 'Impulse');
  485.       $m->append(new Gtk::MenuItem 'Laplacian');
  486.       $m->append(new Gtk::MenuItem 'Poisson');
  487.       my $o = new Gtk::OptionMenu;
  488.       $o->set_menu($m);
  489.       optionmenu_settext($o,@_);
  490.       $o;
  491.    },
  492.    PreviewTypes => sub {
  493.       my $m = new Gtk::Menu;
  494.       $m->append(new Gtk::MenuItem 'Rotate');
  495.       $m->append(new Gtk::MenuItem 'Shear');
  496.       $m->append(new Gtk::MenuItem 'Roll');
  497.       $m->append(new Gtk::MenuItem 'Hue');
  498.       $m->append(new Gtk::MenuItem 'Saturation');
  499.       $m->append(new Gtk::MenuItem 'Brightness');
  500.       $m->append(new Gtk::MenuItem 'Gamma');
  501.       $m->append(new Gtk::MenuItem 'Spiff');
  502.       $m->append(new Gtk::MenuItem 'Dull');
  503.       $m->append(new Gtk::MenuItem 'Grayscale');
  504.       $m->append(new Gtk::MenuItem 'Quantize');
  505.       $m->append(new Gtk::MenuItem 'Despeckle');
  506.       $m->append(new Gtk::MenuItem 'ReduceNoise');
  507.       $m->append(new Gtk::MenuItem 'AddNoise');
  508.       $m->append(new Gtk::MenuItem 'Sharpen');
  509.       $m->append(new Gtk::MenuItem 'Blur');
  510.       $m->append(new Gtk::MenuItem 'Threshold');
  511.       $m->append(new Gtk::MenuItem 'EdgeDetect');
  512.       $m->append(new Gtk::MenuItem 'Spread');
  513.       $m->append(new Gtk::MenuItem 'Solarize');
  514.       $m->append(new Gtk::MenuItem 'Shade');
  515.       $m->append(new Gtk::MenuItem 'Raise');
  516.       $m->append(new Gtk::MenuItem 'Segment');
  517.       $m->append(new Gtk::MenuItem 'Swirl');
  518.       $m->append(new Gtk::MenuItem 'Implode');
  519.       $m->append(new Gtk::MenuItem 'Wave');
  520.       $m->append(new Gtk::MenuItem 'OilPaint');
  521.       $m->append(new Gtk::MenuItem 'Charcoal');
  522.       $m->append(new Gtk::MenuItem 'JPEG');
  523.       my $o = new Gtk::OptionMenu;
  524.       $o->set_menu($m);
  525.       optionmenu_settext($o,@_);
  526.       $o;
  527.    },
  528.    PrimitiveTypes => sub {
  529.       my $m = new Gtk::Menu;
  530.       $m->append(new Gtk::MenuItem 'Point');
  531.       $m->append(new Gtk::MenuItem 'Line');
  532.       $m->append(new Gtk::MenuItem 'Rectangle');
  533.       $m->append(new Gtk::MenuItem 'FillRectangle');
  534.       $m->append(new Gtk::MenuItem 'Circle');
  535.       $m->append(new Gtk::MenuItem 'FillCircle');
  536.       $m->append(new Gtk::MenuItem 'Ellipse');
  537.       $m->append(new Gtk::MenuItem 'FillEllipse');
  538.       $m->append(new Gtk::MenuItem 'Polygon');
  539.       $m->append(new Gtk::MenuItem 'FillPolygon');
  540.       $m->append(new Gtk::MenuItem 'Color');
  541.       $m->append(new Gtk::MenuItem 'Matte');
  542.       $m->append(new Gtk::MenuItem 'Text');
  543.       $m->append(new Gtk::MenuItem 'Image');
  544.       my $o = new Gtk::OptionMenu;
  545.       $o->set_menu($m);
  546.       optionmenu_settext($o,@_);
  547.       $o;
  548.    },
  549.    ResolutionTypes => sub {
  550.       my $m = new Gtk::Menu;
  551.       $m->append(new Gtk::MenuItem 'PixelsPerInch');
  552.       $m->append(new Gtk::MenuItem 'PixelsPerCentimeter');
  553.       my $o = new Gtk::OptionMenu;
  554.       $o->set_menu($m);
  555.       optionmenu_settext($o,@_);
  556.       $o;
  557.    },
  558. );
  559.  
  560. %MagickMethods = (
  561.    Comment => ['comment','StringReference'],
  562.    Label => ['label','StringReference'],
  563.    AddNoise => ['noise','NoiseTypes'],
  564.    Colorize => ['color','StringReference','pen','StringReference'],
  565.    Border => ['geom','StringReference','width','IntegerReference','height','IntegerReference','color','StringReference'],
  566.    Blur => ['factor','DoubleReference'],
  567.    Chop => ['geom','StringReference','width','IntegerReference','height','IntegerReference','x','IntegerReference','y','IntegerReference'],
  568.    Crop => ['geom','StringReference','width','IntegerReference','height','IntegerReference','x','IntegerReference','y','IntegerReference'],
  569.    Despeckle => [],
  570.    Edge => ['factor','DoubleReference'],
  571.    Emboss => [],
  572.    Enhance => [],
  573.    Flip => [],
  574.    Flop => [],
  575.    Frame => ['geom','StringReference','width','IntegerReference','height','IntegerReference','inner','IntegerReference','outer','IntegerReference','color','StringReference'],
  576.    Implode => ['factor','DoubleReference'],
  577.    Magnify => [],
  578.    MedianFilter => [],
  579.    Minify => [],
  580.    OilPaint => ['radius','IntegerReference'],
  581.    ReduceNoise => [],
  582.    Roll => ['geom','StringReference','x','IntegerReference','y','IntegerReference'],
  583.    Rotate => ['degree','DoubleReference','crop','BooleanTypes','sharpen','BooleanTypes'],
  584.    Sample => ['geom','StringReference','width','IntegerReference','height','IntegerReference'],
  585.    Scale => ['geom','StringReference','width','IntegerReference','height','IntegerReference'],
  586.    Shade => ['geom','StringReference','azimuth','DoubleReference','elevat','DoubleReference','color','BooleanTypes'],
  587.    Sharpen => ['factor','DoubleReference'],
  588.    Shear => ['geom','StringReference','x','DoubleReference','y','DoubleReference','crop','BooleanTypes'],
  589.    Spread => ['amount','IntegerReference'],
  590.    Swirl => ['degree','DoubleReference'],
  591.    Zoom => ['geom','StringReference','width','IntegerReference','height','IntegerReference','filter','FilterTypes'],
  592.    IsGrayImage => [],
  593.    Annotate => ['text','StringReference','font','StringReference','point','IntegerReference','density','StringReference','box','StringReference','pen','StringReference','geom','StringReference','server','StringReference','x','IntegerReference','y','IntegerReference','grav','GravityTypes'],
  594.    ColorFloodfill => ['geom','StringReference','x','IntegerReference','y','IntegerReference','pen','StringReference','bordercolor','StringReference'],
  595.    Composite => ['compos','CompositeTypes','image','ImageReference','geom','StringReference','x','IntegerReference','y','IntegerReference','grav','GravityTypes'],
  596.    Contrast => ['sharp','BooleanTypes'],
  597.    CycleColormap => ['amount','IntegerReference'],
  598.    Draw => ['prim','PrimitiveTypes','points','StringReference','meth','MethodTypes','pen','StringReference','linew','IntegerReference','server','StringReference','borderc','StringReference'],
  599.    Equalize => [],
  600.    Gamma => ['gamma','StringReference','red','DoubleReference','green','DoubleReference','blue','DoubleReference'],
  601.    Map => ['image','ImageReference','dither','BooleanTypes'],
  602.    MatteFloodfill => ['geom','StringReference','x','IntegerReference','y','IntegerReference','matte','IntegerReference','bordercolor','StringReference'],
  603.    Modulate => ['factor','StringReference','bright','DoubleReference','satur','DoubleReference','hue','DoubleReference'],
  604.    Negate => ['gray','BooleanTypes'],
  605.    Normalize => [],
  606.    NumberColors => [],
  607.    Opaque => ['color','StringReference','pen','StringReference'],
  608.    Quantize => ['colors','IntegerReference','tree','IntegerReference','colorsp','ColorspaceTypes','dither','BooleanTypes','measure','BooleanTypes','global','BooleanTypes'],
  609.    Raise => ['geom','StringReference','width','IntegerReference','height','IntegerReference','x','IntegerReference','y','IntegerReference','raise','BooleanTypes'],
  610.    Segment => ['colorsp','ColorspaceTypes','verbose','BooleanTypes','clust','DoubleReference','smooth','DoubleReference'],
  611.    Signature => [],
  612.    Solarize => ['factor','DoubleReference'],
  613.    Sync => [],
  614.    Texture => ['texture','ImageReference'],
  615.    Transform => ['crop','StringReference','geom','StringReference','filter','FilterTypes'],
  616.    Transparent => ['color','StringReference'],
  617.    Threshold => ['threshold','DoubleReference'],
  618.    Charcoal => ['factor','StringReference'],
  619.    Trim => [],
  620.    Wave => ['geom','StringReference','ampli','DoubleReference','wave','DoubleReference'],
  621.    Layer => ['layer','LayerTypes'],
  622.    Condense => [],
  623.    Stereo => ['image','ImageReference'],
  624.    Stegano => ['image','ImageReference','offset','IntegerReference'],
  625.    Coalesce => [],
  626. );
  627.  
  628. }
  629.